package org.example.judge.oj;


import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.example.judge_common.util.CompileUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.example.judge_common.properties.JudgeProperties;
import javax.annotation.PostConstruct;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Data
@Component
@Slf4j
public class GoJudgeDruid {

    @Autowired
    private JudgeProperties judgeProperties;

    private static final List<GoJudge> list = Collections.synchronizedList(new ArrayList<>());
    /**
     * 判题机数量
     */
    private static int sum = 0;

    public Integer getSum(){
        return sum;
    }

    public GoJudgeDruid() {

    }

    @PostConstruct
    public void start() {
//        System.out.println(judgeProperties.getJavaCompilePath()==null);
        sum = judgeProperties.getOjSum() + judgeProperties.getOjSumTest();
        //编译器路径
        CompileRun.compiles.put(CompileUnit.C, judgeProperties.getGcCompilePath());
        CompileRun.compiles.put(CompileUnit.GCC, judgeProperties.getGcCompilePath());
        CompileRun.compiles.put(CompileUnit.PYTHON,judgeProperties.getPythonCompilePath());
        CompileRun.compiles.put(CompileUnit.JAVA,judgeProperties.getJavaCompilePath());
        // 创建池子
        for (Integer i = 0; i < sum; i++) {
            String path = new File(judgeProperties.getCodePath(), i.toString()).getPath();
            list.add(new GoJudge(true, new CompileRun(path)));
        }
        log.info("判题机连接池创建完毕,sum：{},测试用判题机个数 :{}",sum,judgeProperties.getOjSumTest());

    }

    public synchronized GoJudge getGoJudge() {
        for (int i = 0; i < judgeProperties.getOjSum(); i++) {
            GoJudge goJudge = list.get(i);
            if (goJudge.isCloseValue()) {
                return this.get(i);
            }
        }
        for (int i = 0; i < judgeProperties.getOjSum(); i++) {
            GoJudge goJudge = list.get(i);
            //上一次获取评测机时间超过两分钟，强行获取
            if (System.currentTimeMillis()-goJudge.getLastTime()>2*60*1000) {
                return this.get(i);
            }
        }
        log.warn("判题机用完，尝试临时占用自定义测试评测机");
        return this.getTestGoJudge();  //无判题评测机，临时占用自定义测试评测机
    }
    private GoJudge get(int i){ //获取第i个
        GoJudge goJudge = list.get(i);
        goJudge.setCloseValue(false);  //状态设置为占用中
        goJudge.setCompiled(false); //设置为未编译
        goJudge.setId(Thread.currentThread().getId());  //设置线程id,评测机引用id
        goJudge.setLastTime(System.currentTimeMillis());
        return goJudge;
    }

    public synchronized GoJudge getTestGoJudge() {  //自定义测试评测机
        for (int i = judgeProperties.getOjSum(); i < sum; i++) {
            GoJudge goJudge = list.get(i);
            if (goJudge.isCloseValue()) {
                return this.get(i);
            }
        }
        for (int i = judgeProperties.getOjSum(); i < sum; i++) {
            GoJudge goJudge = list.get(i);
            if (System.currentTimeMillis()-goJudge.getLastTime()>2*60*1000) {
                return this.get(i);
            }
        }
        log.warn("评测机用完。。。获取失败");
        return null;
    }
}
